package com.jd.jstable.strategy.redis;

import com.alibaba.fastjson.JSON;
import com.jd.jstable.config.KeyMaker;
import com.jd.jstable.config.KeyMode;
import com.jd.jstable.strategy.ExpireTimeStrategy;
import com.jd.jstable.strategy.ResetableStrategy;
import com.jd.jstable.strategy.StrategyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

/**
 * Redis相关的策略
 * Created by chenyipu on 2018/6/6.
 */
@Service("MD5_138cc4666fbd6262a0a57cab833c5dbc_redis")
public class RedisStrategy extends ExpireTimeStrategy implements ResetableStrategy, KeyMaker{

    public final String prefix = "JSTABLE_REDIS";

    @Autowired
    @Qualifier("jstable_______JedisPool")
    JedisPool jedisPool;

    @Override
    public void expire(Object invoker, Method method, Object[] args, Object result, Long time, TimeUnit timeUnit, KeyMode keyMode) {
        String key = generate(invoker, method, args, keyMode);
        Jedis jedis = jedisPool.getResource();
        try {
            jedis.set(key, JSON.toJSONString(result));
            if (timeUnit == null) {
                return;
            }
            Long milliseconds = timeUnit.toMillis(time);
            Integer millisecondsInt = 0;
            if (milliseconds > Integer.MAX_VALUE) {
                millisecondsInt = Integer.MAX_VALUE;
            } else {
                millisecondsInt = milliseconds.intValue();
            }
            if (milliseconds < 0) {
                millisecondsInt = 0;
            }
            jedis.pexpire(key, millisecondsInt);
        }finally {
            if(jedis!=null){
                jedis.close();
            }
        }
    }

    @Override
    public Object solve(Object invoker, Method method, Object[] args, String param, KeyMode keyMode) {
        String key = generate(invoker, method, args, keyMode);
        Jedis jedis = jedisPool.getResource();
        try {
            String resultLast = jedis.get(key);
            if (null == resultLast) {
                return null;
            }
            return JSON.parseObject(resultLast, method.getReturnType());
        }finally {
            if(jedis!=null){
                jedis.close();
            }
        }
    }

    @Override
    public void reset(Object invoker, Method method, Object[] args, String param, KeyMode keyMode) {
        String key = generate(invoker, method, args, keyMode);
        Jedis jedis = jedisPool.getResource();
        try {
            jedis.del(key);
        }finally {
            if(jedis!=null){
                jedis.close();
            }
        }
    }

    @Override
    public String generate(Object invoker, Method method, Object[] args, KeyMode keyMode) {
        return String.format("%s_%s_%s", prefix, keyMode.getPrefix(), StrategyUtil.makeResourceKey(invoker.getClass(), method.getName(), args, keyMode));
    }
}
